package com.ruoyi.sea.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.config.mqtt.MqttCustomerClient;
import com.ruoyi.sea.domain.SeaAlarm;
import com.ruoyi.sea.domain.SeaDataRange;
import com.ruoyi.sea.domain.SeaDevice;
import com.ruoyi.sea.domain.SeaValue;
import com.ruoyi.sea.service.ISeaAlarmService;
import com.ruoyi.sea.service.ISeaDataRangeService;
import com.ruoyi.sea.service.ISeaDeviceService;
import com.ruoyi.sea.service.ISeaValueService;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class TCPClientServiceImpl implements ApplicationRunner {

    @Resource
    private MqttCustomerClient mqttCustomerClient;

    @Resource
    private ISeaValueService seaValueService;

    @Resource
    private RedisCache redisCache;

    @Resource
    ISeaDataRangeService seaDataRangeService;

    @Resource
    ISeaAlarmService seaAlarmService;

    @Resource
    private ISeaDeviceService seaDeviceService;

    // 温度
    private static Float temp = 27F;

    // COD
    private static Float cod  = 0F;

    // ph
    private static Float ph  = 0F;

    // 余氯
    private static Float residualChlorine = 0F;

    // 电导率
    private static Float conductivity = 0F;

    // 氨氮
    private static Float ammoniaNitrogen  = 0F;


    @Override
    public void run(ApplicationArguments args) throws Exception {
        Timer timer = new Timer();
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                // 读取硬件设施数据
                JSONObject json = new JSONObject();
                /**
                 * temp
                 */
                json.put("temp", temp);
                Float temp_redis = redisCache.getCacheObject("temp_history");
                if(temp_redis == null){
                    temp_redis = 0F;
                }
                json.put("temp_compare", Float.compare(temp, temp_redis));

                /**
                 * COD
                 */
                json.put("cod", cod);
                Float cod_redis = redisCache.getCacheObject("cod_history");
                if(cod_redis == null){
                    cod_redis = 0F;
                }
                json.put("cod_compare", Float.compare(cod, cod_redis));

                /**
                 * ph
                 */
                json.put("ph", ph);
                Float ph_redis = redisCache.getCacheObject("ph_history");
                if(ph_redis == null){
                    ph_redis = 0F;
                }
                json.put("ph_compare", Float.compare(ph, ph_redis));

                /**
                 * 余氯
                 */
                json.put("residualChlorine", residualChlorine);
                Float residualChlorine_redis = redisCache.getCacheObject("residualChlorine_history");
                if(residualChlorine_redis == null){
                    residualChlorine_redis = 0F;
                }
                json.put("residualChlorine_compare", Float.compare(residualChlorine, residualChlorine_redis));

                /**
                 * 电导率
                 */
                json.put("conductivity", conductivity);
                Float conductivity_redis = redisCache.getCacheObject("conductivity_history");
                if(conductivity_redis == null){
                    conductivity_redis = 0F;
                }
                json.put("conductivity_compare", Float.compare(conductivity, conductivity_redis));

                /**
                 *  氨氮
                 */
                json.put("ammoniaNitrogen", ammoniaNitrogen);
                Float ammoniaNitrogen_redis = redisCache.getCacheObject("ammoniaNitrogen_history");
                if(ammoniaNitrogen_redis == null){
                    ammoniaNitrogen_redis = 0F;
                }
                json.put("ammoniaNitrogen_compare", Float.compare(ammoniaNitrogen, ammoniaNitrogen_redis));

                mqttCustomerClient.pushlish("sea_status", json.toJSONString());
                // 数据报警检测
                getRealTimeData();
            }
        };
        // 5秒执行一次
        timer.schedule(task, 0 , 5000);
    }

//    public String getToken(){
//        String token = redisCache.getCacheObject("token");
//        if(StringUtils.isBlank(token)){
//            // 创建HttpClient实例
//            try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
//                // 创建HttpGet实例并设置URL
//                HttpGet httpGet = new HttpGet("http://iot.lwbsq.com/api/getToken?loginName=vh250527zyjs&password=vh250527zyjs");
//                // 执行请求并获取响应
//                try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
//                    // 获取响应实体
//                    String responseBody = EntityUtils.toString(response.getEntity());
//                    ObjectMapper mapper = new ObjectMapper();
//                    JsonNode jsonNode = mapper.readTree(responseBody);
//                    token = jsonNode.get("data").get("token").toString().replaceAll("\"", "");
//                    redisCache.setCacheObject("token", token, 1, TimeUnit.HOURS);
//                }
//            } catch (IOException e) {
//                System.out.println("————————————————————————————————————远程连接失败————————————————————————————————————");
//                e.printStackTrace();
//            }
//        }
//        return token;
//    }

    public void getRealTimeData(){
//        // 创建HttpClient实例
//        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
//            // 创建HttpGet实例并设置URL
//            HttpGet httpGet = new HttpGet("http://iot.lwbsq.com/api/data/getRealTimeData");
//            httpGet.addHeader("authorization", getToken());
//            // 执行请求并获取响应
//            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
//                // 获取响应实体
//                String responseBody = EntityUtils.toString(response.getEntity());
//                System.out.println(responseBody);
//                ObjectMapper mapper = new ObjectMapper();
//                JsonNode jsonNode = mapper.readTree(responseBody);
//                if(StringUtils.equals(jsonNode.get("code").toString(), "1000") ){
//                    JsonNode data = jsonNode.get("data").get(0);
//                    // 设备状态
//                    String deviceStatus = data.get("deviceStatus").toString().replaceAll("\"", "");
//                    if(StringUtils.equals(deviceStatus, "normal")){
//                        SeaDevice seaDevice = new SeaDevice();
//                        seaDevice.setId(1L);
//                        seaDevice.setStatus("1");
//                        seaDeviceService.updateSeaDevice(seaDevice);
//                    }
//                    // 纬度
//                    String lat = data.get("lat").toString();
//                    // 经度
//                    String lng = data.get("lng").toString();
//                    // 解析数据
//                    data.get("dataItem").forEach(e -> {
//                        e.get("registerItem").forEach(t -> {
//                            // 温度"
//                            if(StringUtils.equals(t.get("registerName").toString().replaceAll("\"", ""), "温度")){
//                                temp = Float.parseFloat(t.get("data").toString().replaceAll("\"", ""));
//                            }
//                            // PH
//                            if(StringUtils.equals(t.get("registerName").toString().replaceAll("\"", ""), "PH")){
//                                ph = Float.parseFloat(t.get("data").toString().replaceAll("\"", ""));
//                            }
//                            // 电导率
//                            if(StringUtils.equals(t.get("registerName").toString().replaceAll("\"", ""), "电导率")){
//                                conductivity = Float.parseFloat(t.get("data").toString().replaceAll("\"", ""));
//                            }
//                            // 氨氮
//                            if(StringUtils.equals(t.get("registerName").toString().replaceAll("\"", ""), "氨氮")){
//                                ammoniaNitrogen = Float.parseFloat(t.get("data").toString().replaceAll("\"", ""));
//                            }
//                            // COD
//                            if(StringUtils.equals(t.get("registerName").toString().replaceAll("\"", ""), "COD")){
//                                cod = Float.parseFloat(t.get("data").toString().replaceAll("\"", ""));
//                            }
//                            // 余氯
//                            if(StringUtils.equals(t.get("registerName").toString().replaceAll("\"", ""), "余氯")){
//                                residualChlorine = Float.parseFloat(t.get("data").toString().replaceAll("\"", ""));
//                            }
//                        });
//                    });
//                }
//            }
//        } catch (IOException e) {
//            System.out.println("————————————————————————————————————远程连接失败————————————————————————————————————");
//            e.printStackTrace();
//        }
//
        SeaValue  seaValue = new SeaValue();
        seaValue.setId(1L);
        // 单位
        String tempUnit = "°C";
        String salinityUnit = "μs/cm";
        String conductivityUnit = "mg/L";
        String otherUnit = "mg/L";
        // 获取最新报警阈值
        SeaDataRange dataRange = seaDataRangeService.selectSeaDataRangeById(1L);

        /**
         * 温度
         */
        temp = redisCache.getCacheObject("temp");
        if(temp != null){
            seaValue.setWaterTemperature(temp);
            // 判断温度是否在阈值外
            if(dataRange.getWaterTemperatureTop() < temp || temp < dataRange.getWaterTemperatureBottom()){
                // 温度异常
                insetAlarm(1L,
                        "温度异常",
                        temp + "",
                        dataRange.getWaterTemperatureBottom() + tempUnit +" - " + dataRange.getWaterTemperatureTop() + tempUnit,
                        "xxx省xxx市xxx县");
            }

            /**
             * COD
             */
            cod = redisCache.getCacheObject("cod");
            seaValue.setCod(cod);
            // 判断盐是否在阈值外
            if(dataRange.getCodTop() < cod || cod < dataRange.getCodBottom()) {
                // 盐异常
                insetAlarm(1L,
                        "COD异常",
                        cod + "",
                        dataRange.getCodBottom() + salinityUnit +" - " + dataRange.getCodTop() + salinityUnit,
                        "xxx省xxx市xxx县");
            }

            /**
             * PH
             */
            ph = redisCache.getCacheObject("ph");
            seaValue.setPh(ph);
            // 判断ph是否在阈值外
            // BigDecimal 需要处理
            BigDecimal currentPh = new BigDecimal(String.valueOf(ph));
            BigDecimal bottom = new BigDecimal(String.valueOf(dataRange.getPhBottom()));
            BigDecimal top = new BigDecimal(String.valueOf(dataRange.getPhTop()));
            if (currentPh.compareTo(bottom) < 0 || currentPh.compareTo(top) > 0) {
                insetAlarm(1L,
                        "ph异常",
                        currentPh.toString(),
                        bottom + "-" + top,
                        "xxx省xxx市xxx县");
            }

            /**
             * 余氯
             */
            residualChlorine = redisCache.getCacheObject("residualChlorine");
            seaValue.setResidualChlorine(residualChlorine);
            currentPh = new BigDecimal(String.valueOf(residualChlorine));
            bottom = new BigDecimal(String.valueOf(dataRange.getResidualChlorineBottom()));
            top = new BigDecimal(String.valueOf(dataRange.getResidualChlorineTop()));
            // 判断余氯是否在阈值外
            if(currentPh.compareTo(bottom) < 0 || currentPh.compareTo(top) > 0) {
                // 余氯异常
                insetAlarm(1L,
                        "余氯异常",
                        residualChlorine + "",
                        dataRange.getResidualChlorineBottom() + conductivityUnit + " - " + dataRange.getResidualChlorineTop()+conductivityUnit,
                        "xxx省xxx市xxx县");
            }

            /**
             * 电导率
             */
            conductivity = redisCache.getCacheObject("conductivity");
            seaValue.setConductivity(conductivity);

            currentPh = new BigDecimal(String.valueOf(conductivity));
            bottom = new BigDecimal(String.valueOf(dataRange.getConductivityBottom()));
            top = new BigDecimal(String.valueOf(dataRange.getConductivityTop()));
            // 判断电导率是否在阈值外
            if(currentPh.compareTo(bottom) < 0 || currentPh.compareTo(top) > 0) {
                // 溶解氧异常
                insetAlarm(1L,
                        "电导率异常",
                        conductivity + "",
                        dataRange.getConductivityBottom() + otherUnit +" - " + dataRange.getConductivityTop()+otherUnit,
                        "xxx省xxx市xxx县");
            }

            /**
             * 氨氮
             */
            ammoniaNitrogen = redisCache.getCacheObject("ammoniaNitrogen");
            seaValue.setAmmoniaNitrogen(ammoniaNitrogen);

            currentPh = new BigDecimal(String.valueOf(ammoniaNitrogen));
            bottom = new BigDecimal(String.valueOf(dataRange.getAmmoniaNitrogenBottom()));
            top = new BigDecimal(String.valueOf(dataRange.getAmmoniaNitrogenTop()));
            if(currentPh.compareTo(bottom) < 0 || currentPh.compareTo(top) > 0) {
                // 磷酸盐异常
                insetAlarm(1L,
                        "氨氮异常",
                        ammoniaNitrogen + "",
                        dataRange.getAmmoniaNitrogenBottom() + otherUnit +" - " + dataRange.getAmmoniaNitrogenTop()+otherUnit,
                        "xxx省xxx市xxx县");
            }
            // 保存实施记录
            if(seaValue.getPh() != 0F){
                // 设备编号
                seaValue.setDeviceCode("DEVICE0121");
                seaValueService.insertSeaValue(seaValue);
            }
        }
    }


    // 溶氧量约为conductivity千分之6
    private int getConductivity(){
        BigDecimal increment = new BigDecimal("0.006");
        return new BigDecimal(conductivity).multiply(increment).intValue();
    }

    // 磷酸盐约为conductivity十万分之8
    private float getammonia_nitrogen(){
        BigDecimal increment = new BigDecimal("0.000008");
        return new BigDecimal(conductivity).multiply(increment).setScale(1, BigDecimal.ROUND_UP).floatValue();
    }

    // 硅酸盐 conductivity 十万分之1
    private float getAmmoniaNitrogen(){
        BigDecimal increment = new BigDecimal("0.00001");
        return new BigDecimal(conductivity).multiply(increment).setScale(1, BigDecimal.ROUND_UP).floatValue();
    }

    // 硝酸盐约为conductivity万分之15
    private float getNitrate(){
        BigDecimal increment = new BigDecimal("0.00015");
        return new BigDecimal(conductivity).multiply(increment).setScale(1, BigDecimal.ROUND_UP).floatValue();
    }

    // 盐度为conductivity的千分之1
    private int getSalinty(){
        BigDecimal increment = new BigDecimal("0.001");
        return new BigDecimal(conductivity).multiply(increment).intValue();

    }

    public void insetAlarm(Long deviceId, String msg, String value, String standard, String coordinate){
        SeaAlarm seaAlarm = new SeaAlarm();
        seaAlarm.setDeviceId(deviceId);
        seaAlarm.setMsg(msg);
        seaAlarm.setValue(value);
        seaAlarm.setstandard(standard);
        seaAlarm.setCoordinate(coordinate);
        seaAlarm.setCreateTime(new Date());
        int flag = seaAlarmService.insertSeaAlarm(seaAlarm);
        if (flag > 0) {
            log.info("警告 插入成功");
        } else {
            log.info("警告 插入失败");
        }
    }

//    public void fakeMethod(){
//        getRealTimeData();
//    }
}
